package cn.tedu.charging.order.mqtt;

import cn.tedu.charging.common.JsonResult;
import cn.tedu.charging.common.pojo.param.ChargingProcessParam;
import cn.tedu.charging.common.pojo.vo.ChargingProcessVO;
import cn.tedu.charging.common.utils.JsonUtils;
import cn.tedu.charging.order.common.ChargingConstants;
import cn.tedu.charging.order.common.MqttConstants;
import cn.tedu.charging.order.common.OrderStatusConstant;
import cn.tedu.charging.order.dao.mapper.OrderSuccessMapper;
import cn.tedu.charging.order.feign.CostClient;
import cn.tedu.charging.order.pojo.dto.ChargingProcessDto;
import cn.tedu.charging.order.pojo.dto.ChargingResultDto;
import cn.tedu.charging.order.pojo.po.ChargingBillFailPO;
import cn.tedu.charging.order.pojo.po.ChargingBillSuccessPO;
import cn.tedu.charging.order.pojo.po.ChargingProcessPO;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;

/**
 * @Author: Miyako
 * @CreateTime: 2024-10-20  19:23
 * @Description: TODO
 */
@Slf4j
public class MqttConsumer implements MqttCallbackExtended {

    private MqttClient mqttClient;
    private MqttContext mqttContext;



    public MqttConsumer(MqttClient mqttClient , MqttContext mqttContext){
       this.mqttClient=mqttClient;
       this.mqttContext=mqttContext;
    }

    //连接结果
    @Override
    public void connectComplete(boolean reconnect, String serverURI) {
      log.debug("链接成功{}，{}",reconnect,serverURI);
        try {
            mqttClient.subscribe(MqttConstants.TOPIC_CHARGING_RESULT);
            log.debug("订阅开始充电指令结果,topic",MqttConstants.TOPIC_CHARGING_RESULT);
            mqttClient.subscribe(MqttConstants.TOPIC_CHARGING_PROCESS);
            log.debug("订阅充电进度，topic",MqttConstants.TOPIC_CHARGING_PROCESS);
        } catch (MqttException e) {
            //如果异常会重试，不成功后告警
            throw new RuntimeException(e);
        }
            log.debug("成功订阅充电指令结果 topic{}",MqttConstants.TOPIC_CHARGING_RESULT);
    }

    @Override
    public void connectionLost(Throwable throwable) {

    }

    //消息到达节点
    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        
        if (MqttConstants.TOPIC_CHARGING_RESULT.equals(topic)){
            log.debug("处理开始充电的结果消息");
            handleChargingResult(topic, mqttMessage);
        }else if(MqttConstants.TOPIC_CHARGING_PROCESS.equals(topic)){
            log.debug("处理充电进度消息");
            handleChargingProcess(mqttMessage);
        }

    }

    //处理充电进度每次同步时更新计价
    private void handleChargingProcess(MqttMessage mqttMessage) {
        ChargingProcessDto chargingProcessDto = null;
        try {
            //将json字符串转为java对象
            chargingProcessDto = JsonUtils.fromJson(mqttMessage.toString(), ChargingProcessDto.class);
            if (chargingProcessDto != null) {


                //先计算电费
                ChargingProcessVO orderCost = getCost(chargingProcessDto);

                //保存充电数据
                saveChargingProcess(chargingProcessDto,orderCost);

                if (orderCost != null){

                    sendChargingProcess2User(orderCost);
                    //todo 同步充电数据
                    //推送数据给用户webSocket
                }else {
                    log.error("获取价格失败,打印错误日志,接入告警系统");
                }
            }
        }
        catch (Exception e){
            log.error("处理设备同步数据{}出现异常,请检查{}",mqttMessage,e);
        }
    }

    //调用计价服务获取价格信息
    private ChargingProcessVO getCost(ChargingProcessDto chargingProcessDto) {
        CostClient costClient = mqttContext.getCostClient();
        ChargingProcessParam chargingProcessParam = new ChargingProcessParam();
        BeanUtils.copyProperties(chargingProcessDto,chargingProcessParam);
        log.debug("调用计价服务入参{}",chargingProcessParam);
        JsonResult<ChargingProcessVO> chargingProcessVOJsonResult = costClient.calculateCost(chargingProcessParam);
        log.debug("调用计价服务入参{},返回结果{}",chargingProcessParam,chargingProcessVOJsonResult);
        if (chargingProcessVOJsonResult != null){
            return chargingProcessVOJsonResult.getData();
        }else {
            return null;
        }

    }

    private void saveChargingProcess(ChargingProcessDto chargingProcessDto,ChargingProcessVO chargingProcessVO) {
        ChargingProcessPO chargingProcessPO = new ChargingProcessPO();
        BeanUtils.copyProperties(chargingProcessDto,chargingProcessPO);
        chargingProcessPO.setTotalCost(chargingProcessVO.getTotalCost());
        chargingProcessPO.setId(System.currentTimeMillis());
        log.debug("保存充电数据到ES中");
            mqttContext.getChargingProcessESRepository().save(chargingProcessPO);
            log.debug("保存充电数据:{},到ES成功",chargingProcessPO);
    }

    /**
     * @param: []
     * @return: void
     * @description: 推送充电进度给用户
     **/
    private void  sendChargingProcess2User(ChargingProcessVO  chargingProcessVO){
        log.debug("同步充电数据给用户:{}",chargingProcessVO);

        //将对象转换为为Json字符串
        String json = JsonUtils.toJson(chargingProcessVO);

        Boolean success = mqttContext.getWebsocketServer().sendMessage(chargingProcessVO.getUserId(), json);

        log.debug("同步重带你数据给用户结果：{} 用户id：{}.同步数据",success,chargingProcessVO.getUserId(),chargingProcessVO);

    }

    //处理充电结果
    private void handleChargingResult(String topic, MqttMessage mqttMessage) {
        ChargingResultDto  result = null;
        try {
            result = JsonUtils.fromJson(mqttMessage.toString(), ChargingResultDto.class);

            log.debug("收到来自{}消息{}", topic, result.getResult());
            if (result != null) {
                if (ChargingConstants.RESULT_START_CHARGING_SUCCESS.equals(result.getResult())) {
                    log.debug("开始充电");
                    log.debug("保存订单记录----");
                    ChargingBillSuccessPO chargingBillSuccessPO = new ChargingBillSuccessPO();
                    chargingBillSuccessPO.setBillId(result.getOrderNo());
                    //设备返回信息后,将状态修改为正在充电然后保存到数据库
                    chargingBillSuccessPO.setBillStatus(OrderStatusConstant.ORDER_STATUS_PROCESS);
                    OrderSuccessMapper orderSuccessMapper = mqttContext.getOrderSuccessMapper();
                    int row = orderSuccessMapper.insert(chargingBillSuccessPO);
                    log.debug("保存成功订单记录:{},影响行数:{}", chargingBillSuccessPO, row);
                } else {
                    log.debug("设备有响应,设备开始充电失败");
                    ChargingBillFailPO chargingBillFailPO = new ChargingBillFailPO();
                    chargingBillFailPO.setBillId(result.getOrderNo());
                    chargingBillFailPO.setFailDesc("设备有响应,开始充电失败");
                    log.debug("保存失败订单记录:{}", chargingBillFailPO);
                    Integer row = mqttContext.getOrderFailMapper().insert(chargingBillFailPO);
                    log.debug("保存失败订单记录:{},影响行数:{}", chargingBillFailPO, row);
                    log.debug("通知充电的用户,表示歉意,提醒用户更换充电枪");
                    log.debug("通知设备管理员,进行设备的检修");
                }
            }
        }
        catch (Exception e){
            log.debug("返回结果传参出错");
        }
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

    }
}
